/**
 * @file OS_TASK.c
 * @brief 操作系统任务管理文件
 * @details 包含FreeRTOS任务创建、队列管理、GPS状态处理、UI更新等功能
 * @author 开发者
 * @date 创建日期
 */

#include "OS_TASk.h"        // 操作系统任务头文件
#include "FreeRTOS.h"       // FreeRTOS核心头文件
#include "task.h"           // FreeRTOS任务管理头文件
#include "queue.h"          // FreeRTOS队列管理头文件
#include "semphr.h"         // FreeRTOS信号量头文件
#include "KEYS.h"           // 按键驱动头文件
#include "event_groups.h"   // FreeRTOS事件组头文件
#include "ff.h"             // FatFs文件系统头文件
#include "diskio.h"         // 磁盘IO头文件

/* 全局队列句柄定义 */
QueueHandle_t GPS_Stust = NULL;        // GPS状态队列句柄
QueueHandle_t TRK_TRP_Stust = NULL;    // 轨迹和航点状态队列句柄
QueueHandle_t EXTI_AND_TIMER = NULL;   // 外部中断和定时器队列句柄
QueueHandle_t timer_syn = NULL;        // 定时器同步队列句柄

/* 全局任务句柄定义 */
TaskHandle_t  task_stask_handle = NULL;    // 启动任务句柄
TaskHandle_t  lvgl_flash_handle = NULL;    // LVGL刷新任务句柄
TaskHandle_t  lvgl_update_handle = NULL;   // LVGL更新任务句柄
TaskHandle_t  GPS_Stust_update = NULL;     // GPS状态更新任务句柄
TaskHandle_t  TRK_TRP_handle = NULL;       // 轨迹航点更新任务句柄



/**
 * @brief LVGL刷新任务函数
 * @param p 任务参数指针（未使用）
 * @details 负责LVGL图形库的定时刷新，确保UI界面正常显示
 */
void lvgl_flash(void * p) {
    while(1) {
        lv_timer_handler();    // 调用LVGL定时器处理函数
        vTaskDelay(30);        // 延时30个时钟节拍（约30ms）
    }
}

/**
 * @brief LVGL界面更新任务函数
 * @param p 任务参数指针（未使用）
 * @details 负责更新UI界面上的速度、日期时间等信息显示
 */
void lvgl_update(void * p) {
    ui_init();                 // 初始化UI界面
    
    /* 定义显示缓冲区 */
    char YMD[20] = {0};        // 年月日显示缓冲区
    char HMS[20] = {0};        // 时分秒显示缓冲区
    char speed[10] = {0};      // 速度显示缓冲区
    
    while(1) {
        get_speed_H(speed);                    // 获取当前速度值
        lv_label_set_text(ui_kmsp,speed);      // 更新速度显示标签
        rtc_get_time(YMD,HMS);                 // 获取RTC时间
        lv_label_set_text(ui_YMD, YMD);        // 更新日期显示标签
        lv_label_set_text(ui_HMS, HMS);        // 更新时间显示标签
        vTaskDelay(1000);                      // 延时1000个时钟节拍（约1秒）
    }
}

/**
 * @brief GPS状态获取任务函数
 * @param p 任务参数指针（未使用）
 * @details 处理GPS连接状态变化，控制按键初始化和UI显示
 */
void GPS_Stust_get(void * p) {
    uint8_t num = 0;           // 接收到的状态值
    static uint8_t key_start = 0;      // 按键初始化标志
    static uint8_t start_flag = 1;     // 开机启动标志
    
    while(1) {
        /* 从GPS状态队列接收数据 */
        xQueueReceive(
            GPS_Stust,         // 队列句柄
            &num,              // 接收数据指针
            pdTRUE             // 永久等待
        );
        
        if(num == 20) {
            // GPS 未连接状态处理
            lv_obj_clear_flag(ui_GPSUNLINPAGE1, LV_OBJ_FLAG_HIDDEN);  // 显示GPS未连接页面
            if(key_start == 0) {
                key_start = 1;         // 设置按键标志
                keys_deinit();         // 反初始化按键
            }
        } else if(num == 30) {
            // GPS 连接状态处理
            // 开机时保存上次连接信息，置flag为0，key_start=1只会运行这一次
            if(start_flag == 1) {
                key_start = 1;         // 设置按键标志
                start_flag = 0;        // 清除启动标志
            }
            
            // GPS连接成功处理
            lv_obj_add_flag(ui_GPSUNLINK, LV_OBJ_FLAG_HIDDEN);    // 隐藏GPS未连接页面
            lv_obj_clear_flag(ui_GPSLINK,LV_OBJ_FLAG_HIDDEN);     // 显示GPS连接页面
            
            if(key_start == 1) {
                keys_init();           // 初始化按键
                key_start = 0;         // 清除按键标志
            }
        }
    }
}
/**
 * @brief 轨迹和航点更新任务函数
 * @param p 任务参数指针（未使用）
 * @details 定期更新轨迹和航点信息显示
 */
void trk_trp_update(void * p) {
    char TRK[10] = {0};        // 轨迹信息缓冲区
    char TRP[10] = {0};        // 航点信息缓冲区
    
    while(1) {
        TRK_TRP(TRK,TRP);              // 获取轨迹和航点数据
        lv_label_set_text(ui_TRK1,TRK); // 更新轨迹显示标签
        lv_label_set_text(ui_TRP,TRP);   // 更新航点显示标签
        vTaskDelay(1000);               // 延时1000个时钟节拍（约1秒）
    }
}

/**
 * @brief 系统启动任务函数
 * @param p 任务参数指针（未使用）
 * @details 初始化系统硬件和软件组件，创建所有子任务
 */
void task_start(void * p) {
    /* 硬件初始化 */
    uart_config();             // 配置串口1
    uart2_config();            // 配置串口2
    rtc_Init();                // 初始化RTC实时时钟
    printf("MCU \n");          // 打印MCU启动信息
    
    /* 创建消息队列 */
    GPS_Stust = xQueueCreate( 10, sizeof(int));        // 创建GPS状态队列
    TRK_TRP_Stust = xQueueCreate( 10, sizeof(int));    // 创建轨迹航点状态队列
    EXTI_AND_TIMER = xQueueCreate( 10, sizeof(int));   // 创建中断定时器队列
    timer_syn = xQueueCreate( 10, sizeof(char *));     // 创建定时器同步队列
    
    /* 软件组件初始化 */
    lv_init();                 // 初始化LVGL图形库
    lv_port_disp_init();       // 初始化LVGL显示端口
    timer1_init();             // 初始化定时器1

    /*==========进入临界区============*/
    taskENTER_CRITICAL();      // 进入临界区，禁止中断

    /* 创建各个任务 */
    if(xTaskCreate(lvgl_flash,"lvgl_flash",2048,NULL,4,&lvgl_flash_handle) != pdPASS) {
        printf("lvgl_flash creat is down");     // LVGL刷新任务创建失败
    }
    if(xTaskCreate(lvgl_update,"lvgl_update",1024,NULL,2,&lvgl_update_handle) != pdPASS) {
        printf("lvgl_update creat is down");    // LVGL更新任务创建失败
    }
    if(xTaskCreate(GPS_Stust_get,"GPS_Stust_get",512,NULL,2,&GPS_Stust_update) != pdPASS) {
        printf("GPS_Stust_get creat is down");  // GPS状态任务创建失败
    }
    if(xTaskCreate(trk_trp_update,"TRK_TRP_update",512,NULL,2,&TRK_TRP_handle) != pdPASS) {
        printf("trk_trp_update creat is down"); // 轨迹航点任务创建失败
    }
    
    vTaskDelete(NULL);         // 删除当前启动任务
    taskEXIT_CRITICAL();       // 退出临界区，恢复中断
}

/**
 * @brief 任务系统启动函数
 * @details 创建启动任务并启动FreeRTOS调度器
 */
void task_begin() {
    /* 创建启动任务 */
    if(xTaskCreate(task_start,"task_start",1024,NULL,4,&task_stask_handle) != pdPASS) {
        printf("task_start creat is down");     // 启动任务创建失败
    }
    vTaskStartScheduler();     // 启动FreeRTOS调度器
}

